﻿using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace SudukuSolver_Mvvm.ViewModels
{
    public partial class CellViewModel : ObservableObject
    {
        /// <summary>
        /// 保存当前数字在所有可能性中的索引
        /// </summary>
        private int Index { get; set; }

        public bool IsContained
        {
            get
            {
                if (!IsEnabled) return true;
                if (Current == 0) return true;
                var c = GetCases();
                return GetCases().Contains(Current);
            }
        }

        /// <summary>
        /// 保存这个格子所有的可能性
        /// </summary>
        [ObservableProperty]
        private List<int> cases;

        /// <summary>
        /// 保存这个格子是否可以修改，这个只会在初始化格子时设定一次
        /// </summary>
        [ObservableProperty]
        private bool isEnabled;

        /// <summary>
        /// 保存这个格子当前的数字
        /// </summary>
        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(IsContained))]
        private int current;
        partial void OnCurrentChanged(int value)
        {
            // 由于Current属性是自动生成的，所以我们没法直接在set里添加一些额外的逻辑，
            // 因此这个特性提供了一个分部方法，在会自动在set里调用这个方法
        }

        /// <summary>
        /// 这个格子所属于的九宫
        /// </summary>
        private BindingList<BindingList<CellViewModel>> Owner;
        /// <summary>
        /// 在第几个大九宫
        /// </summary>
        private int BigNineIndex;
        /// <summary>
        /// 在这个大九宫中的第几个
        /// </summary>
        private int NineIndex;
        private int RowIndex;
        private int ColIndex;


        /// <summary>
        /// 创建一个格子
        /// </summary>
        /// <param name="owner">这个格子所属于的数独</param>
        /// <param name="bigNine">这个格子在哪一个大九宫中</param>
        /// <param name="nine">这个格子在大九宫中的哪一个位置</param>
        /// <param name="current">当前值</param>
        public CellViewModel(BindingList<BindingList<CellViewModel>> owner, int bigNine, int nine, int current)
        {
            Owner = owner;
            BigNineIndex = bigNine;
            NineIndex = nine;
            RowIndex = bigNine / 3 * 3 + nine / 3;
            ColIndex = bigNine % 3 * 3 + nine % 3;
            Current = current;
            Index = -1;
            if (current == 0)
            {
                IsEnabled = true;
                Cases = new List<int>();
            }
            else
            {
                Cases = new List<int> { current };
                IsEnabled = false;
            }
        }

        /// <summary>
        /// 更新格子的可能性列表
        /// </summary>
        public void UpdateCases()
        {
            if (IsEnabled)
            {
                Cases = GetCases();
                Cases.Sort();
            }
        }

        /// <summary>
        /// 获取当前格子的所有可能性
        /// </summary>
        /// <returns>所有可能性，不包括0</returns>
        private List<int> GetCases()
        {
            // 注意那其他格子数据时，剔除自己


            // 拍平数独，将其编程一维数组
            var flatSuduku = Owner.SelectMany(s => s);

            // 九宫
            var nineNumbers = Owner[BigNineIndex].Select(c => c.Current).Where((_, i) => i != NineIndex);
            // 行
            var rowNumbers = flatSuduku.Where(c => c.RowIndex == RowIndex).Select(c => c.Current).Where((_, i) => i != ColIndex);
            // 列
            var colNumbers = flatSuduku.Where(c => c.ColIndex == ColIndex).Select(c => c.Current).Where((_, i) => i != RowIndex);

            return new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.Except(nineNumbers.Union(rowNumbers).Union(colNumbers)).ToList();
        }

        /// <summary>
        /// 切换到下一个数字
        /// </summary>
        /// <returns>是否切换成功：true，切换到了下一个；false，如果已经是最后一个了，不能切换</returns>
        public bool Next()
        {
            if (Index < Cases.Count - 1)
            {
                Index++; // 下一个数字
                Application.Current.Dispatcher.Invoke(() => { Current = Cases[Index]; });
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 重置格子为初始状态
        /// </summary>
        public void Reset()
        {
            Index = -1;
            Application.Current.Dispatcher.Invoke(() =>
                {
                    Current = 0;
                    Cases = new List<int> { 0 };
                });
        }
    }
}
